﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using blackhouse.BlackApart.Data;
using blackhouse.BlackApart.Business.Payments;
using blackhouse.BlackApart.Business.Apartments;
using System.Globalization;

namespace blackhouse.BlackApart.Business.Reservations {
	public class DaUserApartmentsReservation : IUserApartmentsReservation {

		#region Fields

		private ImpUserApartmentsReservation instance;
		private IReservationDataAccess dataAccess;

		#endregion

		#region Properties

		public int ReservationId {
			get { return this.instance.ReservationId; }
			private set { this.instance.ReservationId = value; }
		}

		public string ReservationNumber {
			get { return this.instance.ReservationNumber; }
			private set { this.instance.ReservationNumber = value; }
		}

		public List<IReservation> Reservations {
			get { return this.instance.Reservations; }
			private set { this.instance.Reservations = value; }
		}

		public IClient Client {
			get { return this.instance.Client; }
		}

		public IPaymentType Payment {
			get { return this.instance.Payment; }
		}

		public DateTime ArrivalDate {
			get { return this.instance.ArrivalDate; }
		}

		public DateTime DepartureDate {
			get { return this.instance.DepartureDate; }
		}

		public TimeSpan ArrivalTime {
			get { return this.instance.ArrivalTime; }
		}

		public double TotalPrice {
			get { return this.instance.TotalPrice; }
		}

		public double TotalPriceWithoutRabat {
			get { return this.instance.TotalPriceWithoutRabat; }
		}

		public float Rabat {
			get { return this.instance.Rabat; }
		}

		public bool VatInvoice {
			get { return this.instance.VatInvoice; }
			set { this.instance.VatInvoice = value; }
		}

		public ReservationStatus Status {
			get { return this.instance.Status; }
			private set { this.instance.Status = value; }
		}

		public Guid Guid {
			get { return this.instance.Guid; }
			private set { this.instance.Guid = value; }
		}

		#endregion

		#region Constructors

		public DaUserApartmentsReservation(IReservationDataAccess reservationDataAccess) {
			this.dataAccess = reservationDataAccess;
			this.instance = new ImpUserApartmentsReservation();
		}

		public DaUserApartmentsReservation(IReservationDataAccess reservationDataAccess, int reservationId)
			: this(reservationDataAccess) {
			if (reservationId > 0)
				this.ReadInstance(reservationId);
		}

		public DaUserApartmentsReservation(IReservationDataAccess reservationDataAccess, string reservationNumber)
			: this(reservationDataAccess) {
			this.ReadInstance(reservationNumber);
		}

		#endregion

		#region IUserApartmentsReservation

		public IUserApartmentsReservation FindByNumber(string reservationNumber) {
			DaUserApartmentsReservation reservation = new DaUserApartmentsReservation(this.dataAccess, reservationNumber);
			if (reservation.ReservationNumber == reservationNumber)
				return reservation;
			else
				return null;
		}

		public void SetClient(string email, string phoneNumber, string firstName, string lastName, string personTitle, string userPrefferCurrency) {
			this.instance.SetClient(email, phoneNumber, firstName, lastName, personTitle, userPrefferCurrency);
		}

		public void SetDates(DateTime startDate, DateTime endDate) {
			this.instance.SetDates(startDate, endDate);
		}

		public void SetPaymentType(IPaymentType paymentType) {
			this.instance.SetPaymentType(paymentType);
		}

		public void SetReservationType(IReservationType reservationType) {
			this.instance.SetReservationType(reservationType);
		}

		public void SetApartment(IApartment apartment, int numberOfPeoples) {
			this.instance.SetApartment(apartment, numberOfPeoples);
		}

		public bool Save() {
			bool state = this.instance.Save();
			if (state) {
				int userReservationId = this.dataAccess.AddReservationHeader(this.instance.Client.Id, this.TotalPrice, this.TotalPriceWithoutRabat, this.Rabat, this.VatInvoice, this.instance.Payment.Id, this.instance.ReservationType.Id);
				if (userReservationId > 0) {
					foreach (IReservation reservation in this.instance.Reservations) {
						state = state && this.dataAccess.JoinReservationHeader(userReservationId, reservation.Id);
						if (state)
							this.ReservationId = userReservationId;
					}
					return state;
				}
			}
			return false;
		}

		#endregion

		#region Methods

		private void ReadInstance(string reservationNumber) {
			ReservationHeaderData data = this.dataAccess.GetReservationHeader(reservationNumber, CultureInfo.CurrentCulture.Name);
			if (reservationNumber != data.Number) return;
			this.SetInstance(data, data.Id);
			this.Reservations = new List<IReservation>();
			ReservationData[] reservations = this.dataAccess.GetReservationsByHeader(data.Id);
			foreach (ReservationData rItem in reservations) {
				this.Reservations.Add(new DaApartmentReservation(rItem, null, this.dataAccess));
			}
		}

		private void ReadInstance(int reservationId) {
			ReservationHeaderData data = this.dataAccess.GetReservationHeader(reservationId, CultureInfo.CurrentCulture.Name);
			this.SetInstance(data, reservationId);
			this.Reservations = new List<IReservation>();
			ReservationData[] reservations = this.dataAccess.GetReservationsByHeader(reservationId);
			foreach (ReservationData rItem in reservations) {
				this.Reservations.Add(new DaApartmentReservation(rItem, null, this.dataAccess));
			}
		}

		private void SetInstance(ReservationHeaderData data, int reservationId) {
			if (data.Id != reservationId) return;
			Factory factory = Factory.Instance();
			this.ReservationId = data.Id;
			this.ReservationNumber = data.Number;
			this.instance.TotalPrice = data.TotalPrice;
			this.instance.TotalPriceWithoutRabat = data.TotalPriceWithoutRabat;
			this.instance.Rabat = data.Rabat;
			this.Guid = new Guid(data.Guid);
			this.VatInvoice = data.VatInvoice;
			ReservationStatus status = new ReservationStatus();
			status.Id = data.StatusId;
            status.MainId = data.MainStatusId;
			status.Name = data.StatusName;
			status.Description = data.StatusDescription;
			this.Status = status;
			this.instance.Client = factory.GetClient(data.ClientId);
			this.SetPaymentType(factory.GetPaymentType(data.PaymentType));
			this.SetDates(data.ArrivalDate, data.DepartureDate);

			this.Reservations = new List<IReservation>();
			ReservationData[] reservations = this.dataAccess.GetReservationsByHeader(reservationId);
			foreach (ReservationData rItem in reservations) {
				this.Reservations.Add(new DaApartmentReservation(rItem, null, this.dataAccess));
			}
		}

		public void SendAsEMail() {
			this.dataAccess.AddMailToSend(this.ReservationId);
		}

		public bool IsAuthentic(Guid toCheck) {
			return this.instance.IsAuthentic(toCheck);
		}

		public bool ChangeStatusTo(int statusId) {
            throw new NotImplementedException("Zmiana statusId na StatusKey");
			//return this.dataAccess.ChangeReservationStatus(this.ReservationId, statusId);
		}

		#endregion

	}
}
